home *** CD-ROM | disk | FTP | other *** search
-
- B A S I C T R A I N I N G
- Part One
- by Steve Estvanik
-
- This is the first of a two part series that shows you the elements of the
- Basic programming language. Basic Training covers the essentials to get you
- started. Advanced Basic (available only to registered users), picks up from
- that point and covers areas such as animation, error trapping and real time
- event programming. (Run the REGISTER program for details on how to obtain
- the second part.)
-
- The dialect of Basic that I use in this first part is based on the extended
- Basic that comes with the IBM PC and most compatibles. The tutorial includes
- many examples. The source code is also included with each tutorial, so you
- can run it, modify it and experiment with it. I recommend that you make a
- backup copy or rename the source files, though, before starting to
- experiment. All the programs in this first part, and most of those in the
- second can be run using just an interpreter, but if you're serious about
- learning Basic, I strongly recommend that you purchase one of the compilers.
-
-
- Part 1. Introduction
-
- Basic History
-
- Basic was invented at Dartmouth in the 50's as a response to the problems of
- instructing a computer. Previously, it was necessary for a programmer to
- understand the computer at the machine level before you could get it to do
- anything useful. This was much like requiring a course in auto mechanics
- before you could hire a taxi. With Basic, you gain an assistant who
- "interprets" their instructions and gets them where you want to go without
- worrying about the "fiddly bits". Basic is only one of a series of
- "languages" which have been developed for this purpose. In its original
- form, it was limited compared to richer languages such as Fortran or Pascal.
- In recent years, especially since the advent of microcomputers, Basic has
- been enhanced and can now stand as tall as any of the other languages. Each
- language has its advocates. In my daily consulting work and game design
- programming, I use many languages routinely. Basic remains one of my choices
- when I need to write a quick program of any sort, especially if it calls for
- graphics. This easy-to-write quality combined with its simple structure
- makes Basic a prime candidate for your first computer language. If you
- already speak one computer language, learning Basic is an easy way to expand
- your fluency.
-
-
- Getting Started
-
- Throughout this tutorial, I try to use commands that are common across all
- Basics. When that's not possible (for example with graphics and sound), I
- use Microsoft Basic for the IBM PC. Most other Basics used on IBM
- compatibles are identical, but occasionally there are small differences.
- Consult your user's manual to check on inconsistencies. When discussing
- compilers, I use the TurboBasic/PowerBasic syntax.
-
- To get started, we'll create a simple, 2 line program. The program itself is
- less important than the mechanics of how to create, save and run a Basic
- program. Don't worry about what each line does right now, we'll cover that
- soon.
-
- Start your version of Basic. If you're using an interpreter, just type:
-
- > basica
- or
- > gwbasic
- or
- > qbasic
-
- This loads interpreter Basic and you'll see the OK prompt. Depending on the
- version of DOS you have on your computer, there may be a different name for
- the basic interpreter. Check your DOS manual for the actual command name.
-
- If you're running a compiler such as PowerBasic or QuickBasic, start the
- program, and run the examples in interactive mode ( alt-R). (There's no OK
- prompt when you use these products.) If you're running Liberty Basic,
- enter the command: win LIBERTY or start the program from within Windows.
-
-
- As an incentive, we'll send you a copy of the Liberty Basic compiler for
- Windows when you register. This compiler lets you run Basic in the Windows
- environment without the need to learn all the complexities of Windows
- programming. To print out the order form, enter the command:
- REGISTER at the DOS prompt.
-
-
- Now type the following 2 lines:
-
- 10 PRINT "hello there...."
- 20 GOTO 10
-
- To test it out, type
-
- RUN
-
- or, if using a compiler, press alt-R (or otherwise invoke the Run command).
-
- You should see your message repeated endlessly. Since your computer has more
- patience than you for this sort of eternal game, press the <control><break>
- keys to end the program. You've just written and run a complete Basic
- program. This short program shows two quite useful statements. "Print"
- causes anything coming after it to be echoed to the screen. "Goto" tells the
- program to jump to the line indicated (in this case 10). Thus our program
- will print the 2 words, then execute line 20. Since this line tells it to go
- back to line 10, we get what's termed an "infinite loop". Usually this is
- the result of a programming error or bug.
-
- This short program also introduces the concept of line numbers. These
- numbers let the interpreter know the order in which to try to execute the
- commands. It also gives you a reference for GOTO commands. Interpreters
- require line numbers. Compilers can use them or not, as you like. Modern
- practise is to avoid them whenever possible, but I'll include them
- occasionally for backwards compatibility.
-
- Our first program lacks elegance, and accomplishes nothing of much use, but
- it gives us something to build on. More importantly, it gives us something
- to save! You can save it now, by typing:
-
- SAVE "Hello"
-
- for the interpreter, or by using the File command, and the Save option if in
- a compiler.
-
- Then leave the Basic interpreter by typing
-
- SYSTEM
-
- Leave the compiler by typing alt-X.
-
- If you want to check that your program is really there, use the directory
- command:
-
- DIR H*.*
-
- You should see "Hello.bas" (plus any other programs you have that start with
- "h"). Note that Basic automatically assigns an extension of ".bas" to any
- program you save. You can override this, but good programming practise
- recommends against this. It will be easier to keep track of you rapidly
- increasing selection of programs if you keep the extensions meaningful. To
- run the program you have two choices. If you want to jump right into the
- program, you just type:
-
- BASICA Hello
-
- This will load the Basic program and immediately begin to run your program.
- Again, you'll need to break in order to stop this monster. Another approach
- would be to load Basic first, then issue the command:
-
- RUN "Hello"
-
- Note that this second case requires the use of quotes, but the result is the
- same, an endless stream of hello's.
-
- The next element we'll look at is the assignment statement. This allows us
- to set the value of variables. Basic has three main categories of elements:
-
- Reserved words -- special words like "print" and "goto"
- that have a special meaning to the interpreter
-
- Constants -- numerical and string values like:
- 2, 3.5 and "Hello there...". (Note that string values
- use quote marks to show their beginning and end.)
-
- Variables -- anything else.
-
- That's not quite fair, but it's close. Variables are what give life to an
- otherwise rather boring collection of reserved words and constants (even
- their names are boring!). A variable is what you create to represent some
- other value. Think of them as containers that can hold many values. For
- example, if I use the variable X, I can put many values into it. This
- process is accomplished with the "LET" statement:
-
- LET X = 10
-
- This says that X now has the value of 10. In fact very few programmers
- bother with the LET statement (Many programmers have yet to discover that
- you can use more than 2 fingers at a time on the keyboard, so they tend to
- be brief.) A terser, and more common way is just to say:
-
- X = 10
-
- This may look familiar to you if you've taken algebra or new-math type
- courses. However, be careful! The "=" sign should be read as "is assigned"
- or "takes the value of". Consider the following:
-
- X = X + 1
-
- This says that X is now to be given the value of whatever X was before, plus
- 1. In this case, 11. One of the advantages of an interpreter is that it can
- give you an immediate response without running a program. You don't need
- special commands to use this mode, just don't use line numbers. Thus if you
- typed the initial line of our program, the interpreter would respond:
-
- Hello there...
-
- Note that the quotes have disappeared. One use you can make of this feature
- is as a calculator. If you type any mathmatical expression, the interpreter
- will give you an answer. Eg, try the following to see how each is
- interpreted:
-
- 2+1
- 2*3
- 4/2
- 4-2
- 2+4*5
- (2+4)*5
-
- Experiment until you feel comfortable with the way that arithmetic is
- handled by the interpreter. Notice, particularly, that the order of
- interpretation depends on both the operator and any parentheses. This is
- called precedence.
-
- Basic also uses some defaults to describe whether a variable is a string,
- integer or real number. Strings are indicated by a '$' as final digit,
- integers as a '%', and real values as '!'. You tell Basic to set this
- default with the command:
-
- DEFINT A-Z
-
- This says any variable starting with the letters A to Z is an integer,
- whether it has a '%' at the end or not. You could also define specific
- variables to be strings or integers, but that starts to get confusing, so I
- use the convention that all variables are integers unless otherwise
- indicated.
-
- Now let's see how this works in a program. We'll start with our hello
- program, already in memory, and add to it:
-
- 10 PRINT "hello there....";X
- 15 X = X + 1
- 20 GOTO 10
-
- Before trying this, make a prediction about what will happen. You should
- always try to predict what your program is going to do. Remembering that
- prediction will help when it does something you didn't anticipate.
-
-
- Exercises
-
- 1. Experiment with various combinations of arithmetic operations, until you
- can predict what the results will be. In particular, try examples which mix
- multiplication and addition. What is the effect of using parentheses?
-
- 2. Use assignment statements to hold intermediate results. EG,
-
- X = 2
- Y = 3
-
- X + Y
- X = X + Y
- PRINT X, Y
-
- (Note that when you assign a value, it isn't printed.)
-
-
- Part 2. STRUCTURE AND STYLE
-
- In the last chapter we looked at the most elementary statements in the Basic
- language. This time, we'll introduce the concept of branching and program
- control. In the next few installments we'll add loops, color, sound and
- arrays. At that point you'll be well equipped to start writing actual
- programs.
-
-
- MORE BASIC CONTROLS
-
- A few more commands useful from within the interpreter:
- LOAD "myprog" --- gets your program from the disk
- LIST --- lists the entire program
- LIST i - j --- lists only lines i to j
- LLIST --- lists the program to your printer
- RENUM --- renumbers your program. any relations within
- your program are preserved.
-
- The compiler doesn't need line numbers, and you can skip them entirely, so
- most of these commands aren't needed. Compilers have direct commands for
- printing a file (usually under the FILE menu item.). I'll continue to use
- line numbers in this tutorial, but my reason for doing so is that it's
- easier to discuss a program when I can refer to particular line numbers. For
- actual programs, I'll usually skip them.
-
- Structured programming is just a small part of the overall concept of
- structured design. The root concept is to build a program from the top down.
- It also discards the concept of flow charts. Here's the reason: Flow charts
- are unnecessarily detailed. By the time you break a problem down to flow
- chart level, you can usually write the code directly. They're so detailed,
- that few programmers go back and change them when the program changes, so
- flow charts are usually out of date as soon as they're written. Structured
- programming does use diagramming techniques, but for our purposes we'll be
- able to use pseudocode for all our designs. We approach the problem by
- defining what we want to do at a very high level. For example, to create a
- checkbook balancer, we might outline the following steps:
-
- Enter initial balance
- Add deposits
- Subtract checks
- Show final balance
- Quit
-
- Now we can elaborate this to describe each step in more detail:
-
-
- Enter initial balance
- Add deposits
- -- ask user if there are any more deposits
- -- if there are then
- get the next deposit
- add that amount to the balance
- .... repeat as necessary
- Subtract checks
- -- ask user if there are any more checks
- -- if there are then
- get the next check
- subtract that amount from the balance
- .... repeat as necessary
- Show final balance
- Quit
-
-
- Note that some items require more elaboration than others. In some cases, we
- could write the Basic code directly, so there's no need for further
- refinement. Now, we're ready to write the actual code. Using this
- structured, top down approach any problems become apparent from the start.
- This text based way of describing a program is termed pseudocode, because
- it's simpler than English, but not rigorous enough to feed to the computer.
- It forms a useful link between human and computer. Well written pseudocode
- is easily converted to any language, and forms an outline of the program. It
- also suggests a preliminary set of comments.
-
-
- IF THEN Statements
-
- All programming statements that we'll look at are merely refinements or
- alternate forms of 3 basic forms: assignments, loops and conditional
- branching. Using only these 3 constructs, any possible program can be
- written. IF THEN, combined with the GOTO is an example of the third type of
- statement, the branch. In its simplest form,
-
- IF { conditional statement } THEN
- { statement 1 }
- ELSE
- { statement 2 }
-
- Last time we saw the simplest version of the loop:
-
- 10 X = X + 1
- 20 PRINT X
- 30 GOTO 10
-
- This is an infinite loop since it has no way to end. One way to end
- it would be by adding a conditional branch:
-
- 10 X = X + 1
- 20 PRINT X
- 30 IF X < 10 GOTO 10
-
- Now, line 20 says that you should jump back up to line 10, ONLY if X is less
- than 10. (Basic uses the symbols <, >, <=, >= and <> to represent the ideas
- "less than", "greater than", "less than or equal to", "greater than or equal
- to" and "not equal to". Try substituting these operations in the fragment
- above to see their effects.
-
- The IF statement evaluates a conditional statement and then follows one of
- several paths. You can have a simple IF statement without an ELSE. This says
- that you want to do something only if the conditional is true, and you have
- no other statements to process. Since the interpreted Basic IF statement
- must all fit on one line, we can also use an expanded form when we have
- several things that we want the statement to perform. We'll see examples of
- this in the sample program, CHECKBK.BAS.
-
- 10 ' checkbk.bas
- 20 ' a simple check book balancing program
- 30 ' copyright 1987, 1992 s m estvanik
- 40 '
- 50 CLS
- 60 PRINT "Check Book Balancing Program"
- 70 PRINT
- 80 INPUT "What is your opening balance";BALANCE
- 90 PRINT
- 95 PRINT "Next transaction? (D/eposit, C/heck, Q/uit)"
- 100 T$=INPUT$(1)
- 110 IF T$ <> "D" AND T$<> "d" GOTO 210 ' is this a deposit?
- 120 INPUT "Amount of deposit";DEPOSIT
- 130 BALANCE = BALANCE + DEPOSIT ' add to balance
- 140 PRINT USING "New balance is $#####.##";BALANCE
- 150 GOTO 90
- 210 IF T$ <> "C" AND T$<> "c" GOTO 300 ' is this a check?
- 220 INPUT "Amount of check";CHECK
- 230 BALANCE = BALANCE - CHECK ' subtract from balance
- 240 PRINT USING "New balance is $#####.##";BALANCE
- 250 GOTO 90
- 300 IF T$ <> "Q" AND T$<> "q" GOTO 90 ' do they want to quit?
- 400 PRINT ' we're done, so show the final balance
- 410 PRINT USING "Final balance is $#####.##";BALANCE
- 430 END
-
- This version of the program uses only the simple statements that we've
- discussed thus far. As we learn more about Basic, the exercises will suggest
- ways you can return to this example to flesh it out. For now, try running
- this program and follow its operation. (The example programs are included in
- the tutorial package in a ready to run fashion. You can also clip out
- segments of code from this tutorial and edit them.)
-
- Since interpreter statements must fit on one line, we're forced to use a
- GOTO in order to create complex IF-THEN-ELSE statements. The compiler
- doesn't limit us this way, so we can construct statements without ever using
- GOTO's.
-
- if X > 10 then
- PRINT X; " is > 10"
- else
- PRINT X; " is <= 10"
-
-
-
- CHECK BOOK BALANCER
-
- This is the first real program we've looked at, so let's examine it in more
- detail. One of the goals of structured programming is to make programs that
- are easy to modify and maintain in the future. To this end, you should
- include a header at the top of each program that describes what it does, and
- most important, when it was last modified and by whom. Then in writing the
- program, use comments wherever they help to explain the flow of the program.
- Comments are ignored by the Basic interpreter and the compiler. They're
- indicated by either the word REM or more commonly, the apostrophe (').
- Comments starting with ' may be either the first or last elements on a line.
- This allows short comments to be placed more precisely. Combined with a
- standard indentation comments make the program structure more readable. For
- example, I indent any statements after an IF statement. I also indent any
- GOTO that starts a statement. In this way you can see that the statements
- are dependent on the IF statement and that the control is passed by the
- GOTO. You'll probably encounter any variants of indenting. The important
- thing is to be consistent. Remember, though, that indenting is solely for
- the human reader's benefit. The computer acts on what it reads, not how it's
- formatted. Improper statements will not improve because of indenting.
-
- If you have multiple IF statements, then the indentations would add up:
-
- IF { condition A} THEN
- IF { condition B } THEN
- { statement 1 }
- ELSE
- { statement 2 }
- ELSE
- { statement 3 }
-
- In this example, if condition A is true, a second check on condition B is
- made, resulting in either statement 1 or 2 being executed. If condition A
- is false, then only statement 3 is executed and condition B isn't even
- checked.
-
- The check book program first clears the screen (CLS), then announces itself
- and uses a new command, INPUT, to ask for an opening balance. The INPUT
- statement prints the string we give it (also called a 'prompt '). It adds a
- question mark and then waits for the user to enter an answer and hit the
- enter key. It stores that value in the variable BALANCE. INPUT is simple to
- use, but does have some drawbacks. Try entering some non-numeric characters.
- INPUT recognizes illegal characters, but its response is less than elegant.
- Later we'll see some better ways for handling data input. After the balance
- is entered, we enter the main loop of the program. The user indicates what
- type of transaction comes next. (Note that we've changed the structure of
- our program so that the user can enter deposits and checks in any order.)
- The INPUT$(1) statement accepts precisely one character from the user and
- doesn't need a carriage return. This is much friendlier since the user only
- needs to press one key each time.
-
- Since we don't care whether the user enters an upper or lower case letter,
- we shouldn't penalize them. Thus we'll allow either when we check. Lines
- 110, 210 and 300 check to see if the value entered is not equal to one of
- the valid codes. Thus in line 110, if T$ is not "T" or "t", we go to 210 to
- check. At any stage, if we find a match, we do the appropriate processing,
- then go back to get the next transaction.
-
- One last suggestion on GOTO's. Do not jump up in the program, unless
- absolutely necessary. That is, in reading a program, the normal flow should
- be downwards. One exception would be a loop such as we have here. Line 90
- starts the loop, and at the end of each transaction we return to it.
-
-
- SUMMARY
-
- We've looked at some basic ideas of structured programming and created our
- first useful program. We've also learned the IF-THEN construct. In addition,
- we've already seen some of the elements of designing user friendly programs.
-
-
- Exercises
-
- 1. Add a third option that allows the user to enter a monthly service fee.
- Decide on a code, and add a new transaction that subtracts the fee. Be sure
- to change the prompt line to show this new code.
-
- 2. The current program just ignores bad codes. Add a message line that
- tells the user that they've entered a bad code, then asks them to reenter
- their choice.
-
- 3. The PRINT USING statements are designed with home use in mind, so they
- only have 5 figures in the display. What happens if the user inputs a
- number such as $100,100 ? Assume that any number greater than 10000 is an
- error. Add an extra check to both the deposit and check section that
- prevents these numbers from being included. You should print an error
- message and then go back to the transaction code input line without making
- any changes to the balance.
-
- 4. Only positive numbers are valid for input. Check that each number
- entered is greater than 0 before allowing it.
-
-
- Part 3. LOOPS, COLORS AND SOUND
-
- In the last section, we learned a simple way to have our programs branch on
- different choices. This time, we'll add more structured loops, color and
- sound. In the following section, we'll look at arrays and data statements.
-
-
- LOOPING
-
- In the previous program, we used GOTO's to move around. This is discouraged
- by purists and for good reason. It's too easy to write spaghetti code with
- meatball logic that jumps all over. This makes it difficult for anyone else
- to read or understand your code. It's even hard to read your own code after
- a week or two. To review, if we wanted to add up a random series of 10
- numbers given by the user, we could write:
-
- 10 x = 1
- 20 sum = 0
- 30 print x
- 40 input "enter a number";n
- 50 sum = sum + n
- 60 x = x + 1
- 70 if x < 11 then goto 30
- 80 print "The sum of the numbers you gave is";sum
-
- Basic provides two other ways to accomplish this, both of which make the
- program more flexible and easier to understand. These are the FOR-NEXT and
- the WHILE-WEND loops. Using FOR-NEXT, we would write
-
- 10 sum = 0
- 20 FOR x = 1 to 10
- 30 print x
- 40 input "enter a number";n
- 50 sum = sum + n
- 60 NEXT x
- 70 print "The sum of the numbers you gave is";sum
-
- Each FOR must have a corresponding NEXT. The FOR-NEXT statements repeat
- automatically. The first number is the initial value, the second is the
- final one. You can also use the STEP command to move by more than one.
- These loops can be nested as shown in the following example. Note that the
- last FOR started must be the first one finished.
-
- 10 input "Starting value (1-10)";x1
- 20 input "Ending value (20-30)";x2
- 30 print
- 40 for x = x1 to x2 step 2
- 50 for y = 1 to 5
- 60 print x*y;
- 70 next y
- 80 print
- 90 next x
-
- Here we print a series of products, five to a line. The semicolon ensures
- that all 5 products are printed on a single line. After Y's FOR-NEXT loop
- is finished, we do a simple PRINT statement to move to the next line.
-
- Another form of looping is the WHILE-WEND pair. Our initial example could
- be reconstructed as:
-
- 10 sum = 0
- 20 x = 1
- 30 WHILE x < 11
- 40 print x
- 50 input "enter a number";n
- 60 sum = sum + n
- 70 x = x + 1
- 80 WEND
- 90 print "The sum of the numbers you gave is";sum
-
- The WHILE statement continues to loop until the condition is achieved.
- Unlike the FOR-NEXT this might not happen. Consider the following:
-
- 10 x = 1
- 20 WHILE x > 11
- 30 input "enter a number";n
- 40 sum = sum + n
- 50 WEND
-
- This program contains a common mistake. The value of X never changes, so
- the loop repeats forever. If you're testing and the program just wanders
- off and never comes back, infinite loops are prime suspects. Check for non-
- terminating WHILE loops by inserting a print statement.
-
- In the above examples, a FOR-NEXT loop is actually preferred, since we
- really intend the loop to be executed a fixed number of times. There are
- many cases when only a WHILE will do. WHILE's can handle loops when the
- ending conditions are unclear. For example:
-
- 10 pts = 0
- 20 die.roll = int(rnd*6) + 1 ' random number bet 1 and 6
- 30 while die.roll <> 6 and pts < 20
- 40 pts = pts + die.roll
- 50 die.roll = int(rnd*6) + 1
- 60 wend
- 70 if die.roll = 6 then pts = 0
- 80 if pts>0 then print "You made";pts;"points" else print"You lost"
-
- This is a simple game in which you have a chance of winning up to 24 points
- if the "die" manages to avoid coming up 6. RND is a Basic function that
- returns a random number between 0 and 1. INT(RND*6) then converts this to a
- random number between 0 and 5. Since dice have no 0's we add one to it.
- Here the while statement has 2 possible ways to end. Either the die rolls a
- 6, or the total points becomes 20 or greater. If the loop ends with a die
- roll of 6, then all points are lost.
-
- Exercise: Make this game more interactive.
-
- After every die roll, show the current points and give the user a chance
- to quit, keeping their current points. Allow an unlimited number of
- points to be accumulated. Don't use any GOTO's in your solution.
-
-
- COLORS
-
- Assuming you have a CGA or EGA card, you can easily add colors and video
- effects to your programs. There are 8 colors, with 4 possibilities for each
- color, defined as follows:
-
-
- "dark" "light" dark, blinking light,blinking
- ------- ------ ------------- --------
- black 0 8 16 24
- blue 1 9 17 25
- green 2 10 18 26
- cyan 3 11 19 27
- red 4 12 20 28
- magenta 5 13 21 29
- brown 6 14 22 30
- white 7 15 23 31
-
-
- On the CGA you can have any of the 32 colors as a foreground color. This is
- the color that letters and other characters will use. You can also set any
- of the 8 colors as a background color. This allows reverse video effects.
- Try the following:
-
- 10 color 7,0
- 20 print "try me"
- 30 color 0,7
- 40 print "try me"
- 50 color 15,1
- 60 print "try me"
- 70 color 31,1
- 80 print "try me"
-
- The program included on the disk, COLORS.BAS gives a more extensive display
- of the color range. First it reproduces the table above, but using actual
- colors for the numbers. Then it shows all combinations of foreground and
- background. Note that if foreground and background are the same, the
- letters can't be read.
-
- Color can be easily abused. Clashing colors or too many colors distract
- rather than attract. Try to avoid using flashing messages for all but the
- most important warnings. In particular, don't use flashing colors for input
- messages. They are difficult to read. Use colors which are easy to read,
- with the more garish colors saved for special cases. The most readable
- color combinations on most displays are:
-
- (bright) white on blue
- (bright) yellow on blue
- (bright) white on red (useful for error messages)
- (bright) yellow on red " " " "
- (bright) white on black
- black on white
- (bright) green on black
- (bright) yellow on black
-
- (bright) indicates either light or dark is ok.
-
- We'll use colors more later when we look at more of the graphics commands.
- For now, try the following problem:
-
-
- Exercise: Add color to the checkbook program given last time. Use the
- following scheme:
-
- First clear the screen to white on blue using the command:
- COLOR 8,1 : CLS
-
- For the first prompts, keep the color as white on blue.
- If a Debit is chosen, change color to bright yellow on blue.
- If a Credit is chosen, change color to bright white on blue.
- If the user makes a mistake, change to bright yellow on red.
-
- Remember to change back to the original setting after each special color.
-
-
- SOUNDS
-
- Basic gives 2 methods for making sounds: SOUND and PLAY. SOUND is easier
- to learn, but harder to use effectively. Its structure is
-
- SOUND frequency, duration
-
- Frequencies are in Hertz (cycles per seconds), durations in clock ticks
- (about 18/second)
-
- SOUND 220, 18 would thus give an A for one second.
-
- In practise, you rarely try to duplicate music using SOUND. Instead it's
- useful for sirens and other sound effects. For example, try
-
- 10 for i = 1 to 10
- 20 sound i*100,5
- 30 next
-
- Or, consider the following:
-
- 10 FOR I=1 TO 9 'phaser sounds
- 20 RII!=I/( 90)
- 30 FOR J= 1000 TO 2700 STEP 200:SOUND J,RII!:NEXT J
- 40 NEXT I
-
- Play with the various loop commands to achieve different effects. Different
- CPU speed may affect these sounds, so they are not generally recommended.
- Most compilers have a timer function that allows you to delay a set amount
- of time.
-
- PLAY has a more complex syntax. I'll briefly introduce it here. The best
- way to learn this command is to practise using it in various ways.
-
- PLAY requires a string that uses Microsoft's music command language. Some
- of the commands are:
-
- A-G with optional # or -, play the notes A-G with sharps or flats.
-
- O n sets the octave. An octave goes from C to B.
- n can range from 0 to 6.
-
- N x plays note x, from 0 to 84. This is an alternative to using
- the notes and octaves, but is less useful if you're
- transcribing from musical notation.
-
- L n sets the length of the note. Can range from 1 to 64.
- Any value, can be played, even 23rd notes!
-
- P n pauses for length n.
-
- T n sets the tempo in quarter notes /minute. For example
- Largo is 40-60, Adagio is 66-76, Allegro is 120-168.
-
- To play a sequence, you just construct a string and give it to PLAY.
-
- x$ = "efg-fed#"
- PLAY "T120 L8 o2" + x$ + "p4 o3 l16 " + x$
-
- We first assign a sequence of notes to x$. Here we're playing E, F, G flat,
- F, E and D sharp. Then we play this sequence of notes at tempo 120, using
- eighth notes in octave 2. We pause for a quarter note's time, then move up
- an octave, change to sixteenth notes and repeat the phrase.
-
- Here's some more interesting music to practise with:
-
- 10 '================== little mathy groves
- 20 PLAY "t160 o3"
- 30 PLAY "l8 g4eee4ddg4efe4.d"
- 40 PLAY "gag4a4gab2 p4ga b4b4b4.b g4b4d4.g "
- 50 PLAY "o2b4 o3 d4 e4f4g4.ge4d4 o2b4o3d4e2."
- 60 X$=INPUT$(1)
- 70 '===================== rising sun blues
- 80 T1$="t200 o2 l4 ge2gb2 o3c+ o3d2 e8d8 o2b2."
- 90 T2$="p2 b o3 e2ef8e.d o2b8o3c."
- 100 PLAY T1$+T2$
-
- These are some phrases from folk songs. Note that I've used an alternate
- way of designating the length in line 30. The G4 says to override the
- default length of 8 for that one note. You can practise by transcribing
- your favorite music, then changing tempo, or playing style.
-
- In the second example, note that several phrases can be described
- independently then built up as needed.
-
-
- 4. ARRAYS and DATA STATEMENTS
-
- Last chapter, we added color and sound to our programming kit. We also saw
- several ways to repeat instructions. In the next chapters we'll finish our
- introduction by looking at more efficient ways to store data, better methods
- for performing repetitive sections of a program, and methods for storing
- data in files.
-
- ARRAYS
- Arrays are a convenient way of representing groups of data. Consider the
- months of the year. We could store them in a program as follows:
-
- MONTH1$ = "JAN"
- MONTH2$ = "FEB"
- MONTH3$ = "MAR"
- MONTH4$ = "APR"
- ...
-
- Then when we want to print month X we could code:
-
- IF X = 1 THEN PRINT MONTH1$
- IF X = 2 THEN PRINT MONTH2$
- IF X = 3 THEN PRINT MONTH3$
- IF X = 4 THEN PRINT MONTH4$
- ...
-
- This isn't terribly efficient. And what if, instead of 12 items, we had
- hundreds or THOUSANDS? We might want to get a total of all incomes in a
- particular group. If there were just a few people to total we could code
-
- TOTAL.INCOME = INCOME1 + INCOME2 + INCOME3...
-
- But do you really want to write the equation for 10,000 people? Luckily we
- have arrays. An array is a grouping of data that still lets us access
- individual elements. An array is defined by a dimension statement:
-
- DIM MONTH$(12)
-
- This defines a group of 13 strings starting with MONTH$(0) and ending with
- MONTH$(12). What's in each one is still up to the programmer and the
- program, but now we can access a particular item much easier. Using the
- months example from above, we still need to define each item or element of
- the array :
-
- MONTH$(1) = "JAN"
- MONTH$(2) = "FEB"
- MONTH$(3) = "MAR"
- MONTH$(4) = "APR"
- ....
-
- So far no big change, but look at how easy it is to find a particular
- value. Now we can get month X directly:
-
- PRINT month$(X)
-
- X is called an index. If we wanted to print all twelve months, we could
- use a loop:
-
- FOR X = 1 to 12
- PRINT MONTH$(X)
- NEXT
-
- Compare this to the hassle of trying to print all months the first way.
- When you have larger arrays, the savings become spectacular. These arrays
- are called singly dimensioned arrays since there is only one index. But we
- can also think of times we'd like to use several dimensions. Maybe we want
- to track the production of several product lines over several months. We
- could set
-
- DIM PRODUCT(10, 12)
-
- This defines an array that will hold sales information on 10 products for
- each of 12 months. Thus PRODUCT(5, 11) would hold the sales for the 5th
- product for the 11th month. Note, we could just as easily defined this as
-
- DIM PRODUCT(12, 10)
-
- where we have data for each month for each product. Now the data for the
- 5th product for the 11th month would be PRODUCT(11, 5). The first method is
- the one usually preferred. Think of the array as starting with the larger
- category (here, product type) on the left, moving to subcategories on the
- right (months).
-
- We can extend the number of dimensions to 3 if we want to show the sales
- for each day of the month:
-
- DIM PRODUCT(10, 12, 31)
-
- In theory you can have 255 dimensions. In reality you'd run out of memory
- well before using all 255. Each added dimension will raise the required
- storage by at least a factor of 2. The total memory space that is available
- to Basic is only 64k. Thus even in our products example, we move from the
- 11 elements of PRODUCT(10) to the 143 of PRODUCT(10,12) to 4576 for
- PRODUCT(10,12,31) ( 11*13*32 ). Another problem is the fact that most
- people have trouble conceptualizing more than 3 or 4 dimensions. Usually
- it's easier to restate the problem. In years of programming I can recall
- only a few instances where more than 3 dimensions made any practical sense.
-
- Arrays form the basis of most data processing applications, especially in
- areas like spreadsheets and statistics. In Basic, an array is considered to
- start from item 0. Many programmers forget about this element and though it
- will take up a little more space, you often can ignore it too. But there are
- some cases where it comes in handy. Suppose we have a 5 by 5 array and want
- to get totals in each direction. Using our product by month example, we'd
- want to get totals for each product for all months and totals for each month
- for all products. Without arrays we'd have to construct separate assignment
- statements for each total. (No, this won't be assigned as an exercise. But
- just think how long it would take to do this, and how many places you could
- mistype and cause an error!) The short program total.bas shows this:
-
- 10 ' totals.bas
- 20 ' do cross totals on an array
- 30 DIM X(5,5)
- 40 X(0,0) = 0 ' grand totals
- 50 FOR I = 1 TO 5
- 60 X(I,0) = 0
- 70 FOR J = 1 TO 5
- 80 X(I,J) = RND(1)*10
- 90 X(I,0) = X(I,0) + X(I,J) ' line totals
- 100 X(0,J) = X(0,J) + X(I,J) ' column totals
- 110 X(0,0) = X(0,0) + X(I,J) ' grand total
- 120 NEXT
- 130 NEXT
- 140 FOR I = 5 TO 0 STEP -1
- 150 IF I = 0 THEN PRINT " " ' extra space
- 160 FOR J = 5 TO 0 STEP - 1
- 170 IF J = 0 THEN PRINT " "; ' extra row
- 180 PRINT USING " ###.## ";X(I,J);
- 190 NEXT
- 200 PRINT
- 210 NEXT
-
- First we define an array X to be 5 by 5. (Later you can expand this to more
- rows and columns, but you may run out of space to display it on the screen.)
- Since we're only going to use the elements that have indices greater than 1,
- we have 3 classes of elements that would otherwise be wasted. These are all
- X(i, 0), X(0, j) and the single element X(0,0). We'll use these as follows:
-
- X(i, 0) will store the total for row i
- X(0, j) will store the total for column j
- X(0, 0) will store the grand total of all rows and columns
-
- Line 40 sets the grand total to 0. Now we have a double-do loop (not to be
- confused with the DOO-WAH loop that's often used for timing.) Since this is
- just a test, we don't want to burden the user by having them enter all the
- data, so in line 80 we just fill in a random number from 0 to 9. Then we
- accumulate the line and column totals in lines 90-110. That's all there is
- to it. To display the results we'll use a pair of reversed loops. This
- will present the 0 indices in the last rows and columns, so the table will
- look more like the spreadsheet format you may be used to. In the lower
- right corner is X(0,0) the grand total.
-
- The PRINT USING statement " ###.##" says to print the value of X using 8
- spaces. The value will be shown as up to 3 digits with 2 additional
- places shown after the decimal place.
-
- ------------------------------------------------
-
- Exercises:
-
- 1. Change the PRINT USING statement to show only 2 digits with one decimal
- place. Reduce the total number of spaces used to 6.
-
- 2. Why do we need the PRINT USING statement in the first place? Hint: take
- it out, replacing it with a simple PRINT X(I,J).
-
- 3.Change this program to allow creation of a spreadsheet that will produce a
- table showing 6 different products in columns, with 12 months as the rows.
- Include labels for each row and col. You can use something simple like
- "Month 9" and "Prod 2", but should use a loop rather explicit numbered
- labels.
- ------------------------------------------------
-
- As you program you'll find countless ways to use arrays. Few programs of
- any size can get along without them. Even small programs benefit. Let's
- look at another use. Program PLAYARRY.BAS shown below defines a series of
- strings.
-
- 1 ' playarry.bas
- 10 PLAY "t220"
- 20 L$(1) = "l8o1 e "
- 30 L$(2) = "l8o1 g "
- 40 L$(3) = "l8o1 f "
- 50 H$(1) ="l32o3 defgab o4 cd"
- 60 H$(2) ="l32o4 edc o3 bagfe"
- 70 H$(3) = "l32 o3 dc o2bagfed"
- 80 H$(4)= "l32 o2 cdefgab o3c"
- 90 FOR K = 1 TO 3
- 100 IF K = 3 THEN PLAY "t220" ELSE PLAY "t180"
- 110 FOR I = 1 TO 12
- 120 IF K = 1 OR K = 3 THEN PLAY L$((I MOD 3)+1)
- 130 IF K = 2 OR K = 3 THEN PLAY H$((I MOD 4)+1)
- 135 ' quit as soon as any key is pressed
- 140 IF INKEY$ > "" THEN 180
- 150 NEXT
- 160 NEXT
- 170 GOTO 90
- 180 END
-
- DATA Statements
-
- So far, whenever we've wanted to define initial values, we've just used
- assignment statements. An alternative is the DATA statement. In its
- simplest form, it consists of a READ statement and a DATA statement
-
- READ I
- DATA 5
-
- When these two statements are executed, I is assigned the value 5. In this
- case there isn't much savings over the more straightforward
-
- I = 5
-
- But the DATA statement is more flexible. You can define a whole array
- with one concise statement:
-
- FOR I = 1 to 10 : READ X(I) : NEXT
- DATA 1,3,4,5,6, 6,5,6,5,6
-
- Otherwise this would take 10 separate statements. You can also make DATA
- statements conditional. RESTORE declares where the initial data statement
- begins.
-
- 10 IF X = 1 THEN RESTORE 20 ELSE RESTORE 30
- 20 DATA 1,2,3
- 30 DATA 4,5,6
- 40 READ I,J,K
-
- Here, when X is 1, I,J,K will be read as 1,2,3 otherwise they will be set to
- 4,5,6. RESTOREs are useful when you have many DATA statements in a program.
- Normal usage places DATA statements near the corresponding READ statements,
- but Basic doesn't care. The program uses the next sequential DATA element.
-
- DATA 1,2,3
- READ X, Y
- ...... [ much more code ]
- DATA 4,5,6
- READ Z
-
- In this fragment, Z is set to 3, since only 2 READ's were done before it.
- Be careful when coding DATA and READ statements. Having too few data
- elements will cause a syntax error. Having more data elements than
- corresponding READ's is allowed, but could cause hard to find errors. A
- safety measure would be to print out the last of a series of read when
- testing so that you can ensure that values are being set the way you
- intended.
-
- Strings in DATA statements cause several additional concerns. When all the
- strings are single words, they could be read in separated by commas, but if
- some of them have commas as part of the item, then you'll need to delimit
- each string by quotes. Thus if we used the statements
-
- DATA Seattle, WA, Bar Harbor, ME
- READ FROM$, TO$
- PRINT FROM$, TO$
-
- we'd see
-
- Seattle WA
-
- In fact we want the city and state to be paired, so we'd need to write
-
- DATA "Seattle, WA", "Bar Harbor, ME"
-
-
- Let's look at another way to use arrays and data statements. DRAWBOX1.BAS
- prints boxes on the screen.
-
- First, a slight digression. CHR$() is a special feature of Basic that
- returns the ASCII equivalent of a number. ASCII is a set of symbols used in
- programming. The first 128 characters (0-127) are rigidly defined. Some
- computers such as the IBM PC define an additional set for the numbers 128-
- 255 but these are not standardized. In the IBM system these include the
- symbols for creating boxes and forms. It's easy to confuse ASCII characters
- and their corresponding numbers. All characters and numerals are ASCII
- characters. Thus the upper case 'A' is 65. Adding 1 to it gives ASCII 66 or
- 'B'. Most confusion comes with numbers. ASCII 49 is the character '1'. Later
- we'll see ways of using this numeric feature in sorting and alphabetizing.
- For now all you need to know is that PRINT CHR$(X) will display the X'th
- ASCII character. Most Basic manuals have an ASCII chart as an Appendix.
- Another option would be to write a short Basic program that prints all
- values. The converse of the CHR$() function is ASC(). This returns the ASCII
- value of a given character. Thus
-
- PRINT ASC("1")
-
- would print 49.
-
- FOR I = 0 to 255
- LPRINT I;CHR$(I) ' print item and ASCII equiv to printer
- NEXT
-
- This will end up 5 pages long. Try writing a program that will format this
- into 8 columns. Thus the first line would have the 0, 32, 64, 96,...
- elements, the second line would have 1, 33, 65, 97,... You can do this with
- either one loop and a long print statement or nested loops and a single
- print statement. Remember that a semicolon (;) after a print line will
- prevent a skip to the next line. If you use this method, you'll need to
- have a separate print statement to shift to the next line.
-
- Now we're ready to draw a box:
-
- 1 ' drawbox1.bas
- 10 DIM CORNER(4)
- 20 KEY OFF
- 30 W = 15 ' width of box
- 40 H = 6 ' height of box
- 50 DATA 205, 186, 201, 187, 188, 200
- 60 READ HORIZ, VERTICAL
- 70 FOR I = 1 TO 4
- 80 READ CORNER(I)
- 90 NEXT
- 100 X = 0
- 110 WHILE X < 1 OR X > 25 - H
- 120 INPUT "Upper left row";X
- 130 WEND
- 140 Y = 0
- 150 WHILE Y < 1 OR Y > 80 - W
- 160 INPUT "Upper left column";Y
- 170 WEND
- 180 COLOR 15,1
- 190 CLS
- 200 LOCATE X,Y
- 210 PRINT CHR$(CORNER(1)); ' top line
- 220 FOR I = 1 TO W-2 : PRINT CHR$(HORIZ); : NEXT
- 230 PRINT CHR$(CORNER(2));
- 240 FOR J = 1 TO H - 2 ' create middle section
- 250 LOCATE X+J,Y
- 260 PRINT CHR$(VERTICAL);
- 270 FOR I = 1 TO W-2 : PRINT CHR$(32); : NEXT
- 280 PRINT CHR$(VERTICAL);
- 290 NEXT
- 300 LOCATE X+H-1, Y
- 310 PRINT CHR$(CORNER(4)); ' bottom line
- 320 FOR I = 1 TO W-2 : PRINT CHR$(HORIZ); : NEXT
- 330 PRINT CHR$(CORNER(3));
- 340 END
-
- First we set the width and height of the box we want to draw. Then we
- read in values for the horizontal and vertical linedrawing characters ═
- and ║. These are ascii values 205 and 186. Line 60 reads their values and
- stores them as variables HORIZ and VERTICAL. Next, we need the the four
- corners:
-
- ╔ ╗
-
- ╚ ╝
-
- The ascii values for the corners (201, 187, 188 and 200) are stroed in an
- array (lines 70-90). We next ask for row and column coordinates. The
- program draws the upper left corner, a row of horizontal characters and the
- upper right corner. For each intermediate line, we draw a vertical section,
- spaces and another vertical. We finish with the 2 lower corners connected
- by another horizontal line.
-
-
- Exercises
-
- 1. Allow user to draw several boxes without erasing them You'll need to
- keep the input on several lines, eg, lines 21 and 22. Clear each line
- before prompting for new data.
-
- 2. Check the ASCII table in the back of your Basic manual. Find the
- characters that can be used to make a single lined box and add them to the
- program. Use a 2 dimensional array. That is redefine the arrays to be
- CORNER(4,2), HORIZ(2), VERTICAL(2) and then ask the user whether they want
- a single or double lined box.
-
- 3. More involved: This box is drawn from the top down. An alternative
- would be to draw it as if a pen were sketching it. Rewrite the program to
- draw the first line, then drop down the right hand side, come back along
- the bottom right to left, then draw up to the original corner. For the
- sides you'll need to recalculate the x,y position each time. A FOR-NEXT
- loop works fine.
-
- ---------------------------------------------------------
-
- We've looked at several different applications of arrays. We've also
- managed to review many of the constructs that we covered in previous
- sessions. In the next installments we'll refine these ideas as we start
- considering how to build larger programs in a structured manner.
-
- Exercise
- In preparation for next time, try this as a final exercise:
-
- DIM DAYS(12)
- DATA 31,28,31, 30,31,30, 31,31,30, 31,30,31
- FOR I = 1 TO 12 : READ DAYS(I) : NEXT
-
- Write a short program that takes as input a pair of numbers -- month and
- day. Calculate the number of days elapsed since the start of the year and
- the number of days till the end of the year.
-
-
- End of Part One
- This completes the first part of BASIC TRAINING TUTORIAL. The next section
- covers Files, graphics and other topics. It's still part of the BASIC
- TRAINING shareware package.
-
- If you're interested in studying more of what Basic can do, and what a
- compiler can add, the next Tutorial in this series will help. When you
- register, you get it for free.
-
- ADVANCED BASIC. Topics include: Animation techniques, Shape Shifting
- techniques, Error Handling, Chaining, Windows, Peek / poke, Bload / bsave,
- Plus, details on differences between interpreters and compilers. And
- complete source for all examples. Advanced Basic is ONLY available to
- registered users.
-
- Registration costs only $20, and you will receive The Advanced Basic
- Tutorial as a bonus, along with more source code for all the examples in
- that tutorial.
-
- In addition, when you register you also get an evaluation copy of the
- LIBERTY Basic compiler for Windows. This program lets you develop Basic
- programs in the Windows environment, without the need for the Windows
- Software Development Kit.
-
- To Register, return to DOS, and enter the command:
- REGISTER
- An order form will be printed for you. Or send $20 + $4 shipping to:
- Cascoly Software
- 4528 36th Ave NE
- Seattle WA 98105
-
-